"""
数据模型定义：包含订单、持仓等核心数据结构
"""
import random
from datetime import datetime, date
from enum import Enum
from copy import copy
from utils.logger import sys_logger

logger = sys_logger.getChild('Model')

class OrderStatus(Enum):
    """订单状态枚举"""
    PENDING = "PENDING"        # 订单已创建
    SUBMITTED = "SUBMITTED"    # 已提交交易所
    PARTIAL_FILLED = "PARTIAL_FILLED"  # 部分成交
    FILLED = "FILLED"          # 全部成交
    CANCELLED = "CANCELLED"    # 已撤销
    REJECTED = "REJECTED"      # 被拒绝
    UNKNOWN = "UNKNOWN"        # 未知状态

class OrderDirection(Enum):
    """订单方向枚举"""
    BUY = "BUY"
    SELL = "SELL"

class OrderType(Enum):
    """订单报价类型"""
    FIX = 'FIX'
    MARKET = 'MARKET'

class Order:
    """订单数据模型"""

    def __init__(self, symbol: str, direction: OrderDirection, price: float, volume: int, type: OrderType = OrderType.FIX):
        """
        初始化订单
        :param symbol: 标的代码，如'600519.SH'
        :param direction: 买卖方向
        :param price: 订单价格
        :param volume: 订单数量(股)
        """

        #参数校验
        if not symbol.endswith(('.SH', '.SZ')):
            logger.warning(f"非标准证券代码格式: {symbol}")

        if price < 0:
            raise ValueError("委托价格必须大于0")

        if volume % 100 != 0:
            raise ValueError("委托数量必须为整手数（100的倍数）")

        self.id = self._generate_id()
        self.order_id = 0
        self.symbol = symbol
        self.direction = direction
        self.price = price
        self.type = type
        self.volume = volume
        self.filled_volume = 0       # 已成交数量
        self.filled_price = 0       # 已成交均价
        self.status = OrderStatus.PENDING
        self.create_time = datetime.now()
        self.update_time = self.create_time

        logger.debug(f"创建订单类实例 {self.order_id} {self.symbol} {direction.value} {volume}股 @ {price:.2f}")

    def _generate_id(self) -> str:
        id = datetime.now().strftime('%Y%m%d%H%M%S') + str(random.randint(100, 999))
        return id

    def set_id(self, id: int) -> None:
        self.id = id

    def set_order_id(self, order_id: int) -> None:
        self.order_id = order_id

    def copy(self):
        """创建对象的浅拷贝"""
        return copy(self)

    def update_status(self, new_status: OrderStatus, filled_volume: int = 0, filled_price: float = 0) -> None:
        """
        更新订单状态
        :param new_status: 新状态
        :param filled_volume: 已成交数量
        """
        # 状态流转校验
        if self.status in [OrderStatus.FILLED, OrderStatus.CANCELLED, OrderStatus.REJECTED]:
            error_msg = f"禁止更新终态订单 {self.order_id} 当前状态:{self.status}"
            logger.error(error_msg)
            raise ValueError(error_msg)

        # 成交数量校验
        if filled_volume < 0 or filled_volume > self.volume:
            error_msg = f"无效成交数量 {filled_volume}，范围应为0-{self.volume}"
            logger.error(error_msg)
            raise ValueError(error_msg)

        # 成交价格校验
        if filled_price < 0:
            error_msg = f"无效成交价格价格 {filled_price}, 必须大于0"
            logger.error(error_msg)
            raise ValueError(error_msg)

        # 状态变更日志
        log_msg = (f"订单状态更新 {self.order_id}: {self.status.name} -> {new_status.name} "
                 f"订单成交: {self.filled_volume} -> {filled_volume}, 均价 {filled_price}")
        logger.debug(log_msg)

        self.status = new_status
        if new_status == OrderStatus.FILLED:
            self.filled_volume = filled_volume
            self.filled_price = filled_price

        self.update_time = datetime.now()

class Position:
    """持仓数据模型"""

    def __init__(self, symbol: str, volume: int = 0, price: float = 0):
        """
        初始化持仓
        :param symbol: 标的代码
        """
        self.symbol = symbol
        self.total_volume = volume       # 总持仓量
        self.available_volume = volume   # 可用持仓
        self.avg_price = 0.0             # 平均成本价
        self.highest_price = 0.0         # 持仓期间最高价记录
        self.highest_date = None         # 持仓期间最高价时间
        self.cur_price = 0.0             # 当前价格
        self.market_value = 0.0          # 当前市值
        self.float_pnl = 0.0             # 浮动盈亏
        self.entry_date = None           # 买入时间

    def update_positon(self, volume, available_volume, price: float = 0):
        self.available_volume += available_volume

        if self.avg_price == 0:
            self.avg_price = price

        if volume != 0:
            new_volume = self.total_volume + volume
            if new_volume != 0:
                new_avg_price = (self.avg_price * self.total_volume + price * volume) / new_volume
            else:
                new_avg_price = 0

            self.total_volume = new_volume
            self.avg_price = new_avg_price

        self.cur_price = price
        self.market_value = self.total_volume * price
        self.float_pnl = self.market_value - (self.total_volume * self.avg_price)

    def update_price(self, date: date, price: float) -> None:
        """根据最新价格更新市值和盈亏"""
        if price > self.highest_price:
            self.highest_price = price
            self.highest_date = date

        self.cur_price = price
        self.market_value = self.total_volume * price
        self.float_pnl = self.market_value - (self.total_volume * self.avg_price)